package cn.com.nes.site.module.service.design;

import cn.com.nes.common.util.ParameterUtil;
import cn.com.nes.mybatis.agent.monitor.entity.HyBoundingstructure;
import cn.com.nes.mybatis.agent.monitor.entity.HyTimbering;
import cn.com.nes.mybatis.agent.monitor.mapper.HyBoundingstructureMapper;
import cn.com.nes.mybatis.agent.monitor.mapper.HyTimberingMapper;
import cn.com.nes.mybatis.agent.ope.mapper.LoadMapper;
import cn.com.nes.site.entity.DataReq;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.dto.AreaLift;
import cn.com.nes.site.entity.dto.HeatPumpResDto;
import cn.com.nes.site.entity.vo.design.CalculateCostVo;
import cn.com.nes.site.entity.vo.design.HeatingSysVo;
import cn.com.nes.site.module.dao.design.CalculateDaoImpl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CalculateService {

    @Resource
    private CalculateDaoImpl impl;

    @Resource
    private LoadMapper loadMapper;

    @Resource
    private HyBoundingstructureMapper boundingstructureMapper;

    @Resource
    private HyTimberingMapper timberingMapper;

    public PageData getCityTreeOfWeatherParamManage(DataReq req) throws Exception {
        return impl.getCityTreeOfWeatherParamManage(req);
    }

    public PageData getDetailsOfWeatherParamManage(DataReq req) throws Exception {
        return impl.getDetailsOfWeatherParamManage(req);
    }

    public PageData getTypeTreeOfBuildingEnvelopeManage(DataReq req) throws Exception {
        return impl.getTypeTreeOfBuildingEnvelopeManage(req);
    }

    public PageData getDetailsOfOfBuildingEnvelopeManage(DataReq req) throws Exception {
        return impl.getDetailsOfOfBuildingEnvelopeManage(req);
    }

    public PageData getTypeTreeOfMaterialQualityManage(DataReq req) throws Exception {
        return impl.getTypeTreeOfMaterialQualityManage(req);
    }

    public PageData getDetailsOfMaterialQualityManage(DataReq req) throws Exception {
        return impl.getDetailsOfMaterialQualityManage(req);
    }

    public PageData saveMaterialQuality(DataReq req) throws Exception {
        return impl.saveMaterialQuality(req);
    }


    public PageData calculateHeatLoad(DataReq req) throws Exception {
        return impl.calculateHeatLoad(req);
    }

    public PageData calculateAndSave(DataReq req, CalculateCostVo vo) throws Exception {
        PageData res = new PageData();
        res.setRetCode(9);
        res.setRetMessage("计算失败");

        HeatPumpResDto dto = new HeatPumpResDto();
        dto.setEntry(vo);

        //保留俩位小数
        DecimalFormat df = new DecimalFormat("#0.00");
        //筛选住宅类型获取指定单位负荷指标
        if ("城镇住宅".equals(vo.getBuildingType())) {
            vo.setField("city_load");
        } else if ("城镇节能住宅".equals(vo.getBuildingType())) {
            vo.setField("ec_load");
        } else {
            vo.setField("rural_load");
        }
        String xzqhdm = vo.getXzqhdm();

        if (xzqhdm.length() > 4) {
            vo.setXzqhdm(xzqhdm.substring(0, 4));
            Double aDouble = loadMapper.queryLoadIndex(vo);
            if (ObjectUtil.isNotNull(aDouble)) {
                dto.setUnitLoadIndex(aDouble);
            } else {
                vo.setXzqhdm(xzqhdm.substring(0, 2));
                dto.setUnitLoadIndex(loadMapper.queryLoadIndex(vo));
            }
        } else {
            vo.setXzqhdm(xzqhdm.substring(0, 2));
            dto.setUnitLoadIndex(loadMapper.queryLoadIndex(vo));
        }

        //标准热负荷=建筑面积*单位负荷指标[设计负荷指标]
        Integer buildingEnvelopeId = ParameterUtil.getInteger(req, "RFHbody4ListID"); // 围护结构ID
        Double floorage = Double.parseDouble(String.valueOf(req.getReqData().get("RFHbuildingArea"))); // 建筑面积
        Double winterIndoorDesignTemperature = Double.parseDouble(String.valueOf(req.getReqData().get("RFHDongJiSNSJWD"))); // 冬季室内设计温度
        Double winterOutdoorTemperature = Double.parseDouble(String.valueOf(req.getReqData().get("RFHDjKtSwGqWd"))); // 冬季室外温度
        HyBoundingstructure boundingstructure = boundingstructureMapper.selectById(buildingEnvelopeId);
        String[] houDuS = boundingstructure.getHouDuS().split(",");
        String[] tids = boundingstructure.getTIdS().split(",");
        List<Integer> tidList = new ArrayList<>();
        // 创建材质和厚度映射关系
        HashMap<Integer, String> houdus = new HashMap<>();
        for (int i = 0; i < tids.length; i++) {
            houdus.put(Integer.valueOf(tids[i]), houDuS[i]);
            tidList.add(Integer.valueOf(tids[i]));
        }
        List<HyTimbering> timberingList = timberingMapper.selectBatchIds(tidList);
        floorage = Math.sqrt(floorage) * 4 * 2.8 + 2 * floorage;
        Double heatLoad = heatLoad(floorage, winterIndoorDesignTemperature, winterOutdoorTemperature, houdus, timberingList);
        dto.setStandardHeatLoad(heatLoad);

        //空气源热泵系统热负荷=标准热负荷*1.15-1.2     (不小于0)
        dto.setSysHeatLoad(Double.valueOf(df.format(Math.max(dto.getStandardHeatLoad() * 1.15, 1.2) - 1.2)));
        //选用台数=空气源热泵系统热负荷/铭牌制热量         （向上取整）
        dto.setTowerNum((int) Math.ceil(Math.max(1, dto.getSysHeatLoad() / vo.getHeatingCapacity())));
        //按照机组数量取费的方案报价    （万元）  选用台数 * 单价(price)   (最少为一台)
        dto.setTotalPrice(((vo.getPrice() * dto.getTowerNum() / 10000.0)));
        //流量=3.6 * 1.1 * Q/(4.2 * ∆T)    ∆T(5或10) 【供回水温差】  Q☞空气源热泵系统热负荷
        Double v = 3.6 * 1.1 * dto.getSysHeatLoad() / (4.2 * vo.getTemperatureDifference());
        dto.setFlow(Double.valueOf(df.format(v)));

        //对应  管径 是去查☞标准流速对应下的流量M3/h  (1.2-2.5)最接近的
        dto.setPipeDiameter(loadMapper.queryPipeDiameter(dto.getFlow()).get("pipeDiameter").toString());
        //扬程(M)  无法计算 查到的 ☞ 去最近的取大 建筑面积大于50000的话扬程取50000的扬程
        AreaLift areaLift = loadMapper.selectAreAndLiftByT(vo);
        if (vo.getBuildingArea() >= areaLift.getBuildingArea()) {
            //建筑面积大于数据库对大面积  扬程按最大面积的走
            dto.setLift(areaLift.getLift());
        } else {
            //建筑面积小于最大面积的   找最靠近的
            Map areaLiftResMap = loadMapper.queryLift(vo);
            dto.setLift(((double) areaLiftResMap.get("lift")));
        }
        //热泵功率  ☞ 台数*制热额定功率
        dto.setHeatPower(Double.valueOf(df.format(vo.getZredgl() * dto.getTowerNum())));
        //计算功率(KW)= 2.73 * 流量 * 扬程/(1000*0.6)   热泵功率
        Double jsGl = Double.valueOf(df.format(2.73 * dto.getFlow() * dto.getLift() / (1000 * 0.6)));
        //实际功率(KW)  是 计算功率查☞电机标准功率（KW）取最接近的
        dto.setActualPower(((double) loadMapper.queryStandard(jsGl).get("power")));

        //配电功率（KW）=(制热额定功率 * 台数+实际功率)*1.1
        dto.setElectricPower(Double.valueOf(df.format((vo.getZredgl() * dto.getTowerNum() + dto.getActualPower()) * 1.1)));
        //预计收入  （供暖费+补贴+管理）*建筑面积
        dto.setProjectedIncome(Double.valueOf(df.format(vo.getBuildingArea() * (vo.getHeatingCharges() + vo.getSubsidy() + vo.getManagementFee()))));
        //预计支出
        Double fd = (vo.getFdRatio() == null ? 0 : vo.getFdRatio()) / 100.0 * 24.0 * vo.getFdjg() * vo.getHeatingPeriod() * dto.getElectricPower();
        Double gd = (vo.getGdRatio() == null ? 0 : vo.getGdRatio()) / 100.0 * 24.0 * vo.getGdjg() * vo.getHeatingPeriod() * dto.getElectricPower();
        Double pd = (vo.getPdRatio() == null ? 0 : vo.getPdRatio()) / 100.0 * 24.0 * vo.getPdjg() * vo.getHeatingPeriod() * dto.getElectricPower();
        Double jd = (vo.getJdRatio() == null ? 0 : vo.getJdRatio()) / 100.0 * 24.0 * vo.getJdjg() * vo.getHeatingPeriod() * dto.getElectricPower();
        Double zc = Double.valueOf(df.format(fd + gd + pd + jd));
        dto.setEstimatedSpending(zc);
        HeatingSysVo params = new HeatingSysVo(dto, vo);
        String fullName = loadMapper.queryfullNameByXzqhdm(xzqhdm);
        params.setAddress(fullName.replaceAll("->",""));
        loadMapper.insertHeatingSys(params);
        dto.setId(loadMapper.selectHeatingSysMaxId());

        HashMap<String, Object> map = new HashMap<>();
        map.put("data", dto);
        res.setData(map);
        res.setRetCode(0);
        res.setRetMessage("ok");
        return res;
    }

    /**
     * 热负荷计算
     *
     * @param f           建筑面积
     * @param tn          室内温度
     * @param tw          室外温度
     * @param houDuSSplit 厚度
     * @param materials   材质
     * @return
     */
    private Double heatLoad(Double f, Double tn, Double tw, HashMap<Integer, String> houDuSSplit, List<HyTimbering> materials) {
        int a = 1; // 温差修正系数，当前指定为1
        DecimalFormat df = new DecimalFormat("#0.000");
        Double k = 0d;
        for (int i = 0; i < materials.size(); i++) {
            BigDecimal drXs = new BigDecimal(String.valueOf(materials.get(i).getDrXs()));
            drXs = drXs.setScale(3, BigDecimal.ROUND_HALF_UP);
            Double drxs = Double.parseDouble(drXs.toString());
            BigDecimal houDu = new BigDecimal(houDuSSplit.get(materials.get(i).getId()));
            houDu = houDu.divide(new BigDecimal(1000));
            houDu= houDu.setScale(3, BigDecimal.ROUND_HALF_UP);
            Double houdu = Double.parseDouble(houDu.toString());
            String name = (String) materials.get(i).getName();
//            System.out.println(name + " 厚度：" + houdu + " 导热系数：" + drxs);
            Double z = Double.parseDouble(new BigDecimal(String.valueOf(houdu / drxs)).setScale(3, BigDecimal.ROUND_HALF_UP).toString());
            k = k + z;
        }
        k = Double.parseDouble(new BigDecimal(k).setScale(3, BigDecimal.ROUND_HALF_UP).toString());
        k = 1 / (k + 0.11 + 0.04);
        k = Double.valueOf(df.format(k));
//        System.out.println("k = " + k);
        double s = k * f * (tn - tw) * a;
        return s;
    }

    public PageData getCalculate(DataReq req) throws Exception {
        Integer id = ParameterUtil.getInteger(req, "id");
        String address = ParameterUtil.getString(req, "address");
        Integer pageid = ObjectUtil.isNull(ParameterUtil.getInteger(req, "pageid")) ? 1 : ParameterUtil.getInteger(req, "pageid");
        Integer pagesize = ObjectUtil.isNull(ParameterUtil.getInteger(req, "pagesize")) ? 10 : ParameterUtil.getInteger(req, "pagesize");
        String companyId = req.getUinfo().getCompanyId();
        final Page<HeatingSysVo> page = new Page<>(pageid, pagesize);
        List<HeatingSysVo> res = loadMapper.selectHeatingSysList(page, id, companyId, address);
        page.setRecords(res);
        return PageData.ok(page, res);
    }

    public PageData deleteCalculate(DataReq req) throws Exception {
        return  impl.deleteCalculate(req);
    }
}
